home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / Net / IPv4.php < prev    next >
Encoding:
PHP Script  |  2005-12-02  |  13.8 KB  |  459 lines

  1. <?php
  2. /**
  3. * Class to provide IPv4 calculations
  4. *
  5. * PHP versions 4 and 5
  6. *
  7. * LICENSE: This source file is subject to version 3.01 of the PHP license
  8. * that is available through the world-wide-web at the following URI:
  9. * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
  10. * the PHP License and are unable to obtain it through the web, please
  11. * send a note to license@php.net so we can mail you a copy immediately.
  12. *
  13. * @category   Net
  14. * @package    Net_IPv4
  15. * @author     Eric Kilfoil <edk@ypass.net>
  16. * @author     Marco Kaiser <bate@php.net>
  17. * @author     Florian Anderiasch <fa@php.net>
  18. * @copyright  1997-2005 The PHP Group
  19. * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  20. * @version    CVS: $Id: IPv4.php,v 1.11 2005/11/29 12:56:35 fa Exp $
  21. * @link       http://pear.php.net/package/Net_IPv4
  22. */
  23.  
  24. require_once 'PEAR.php';
  25.  
  26. // {{{ GLOBALS
  27. /**
  28.  * Map of bitmasks to subnets
  29.  *
  30.  * This array contains every valid netmask.  The index of the dot quad
  31.  * netmask value is the corresponding CIDR notation (bitmask).
  32.  *
  33.  * @global array $GLOBALS['Net_IPv4_Netmask_Map']
  34.  */
  35. $GLOBALS['Net_IPv4_Netmask_Map'] = array(
  36.             0 => "0.0.0.0",
  37.             1 => "128.0.0.0",
  38.             2 => "192.0.0.0",
  39.             3 => "224.0.0.0",
  40.             4 => "240.0.0.0",
  41.             5 => "248.0.0.0",
  42.             6 => "252.0.0.0",
  43.             7 => "254.0.0.0",
  44.             8 => "255.0.0.0",
  45.             9 => "255.128.0.0",
  46.             10 => "255.192.0.0",
  47.             11 => "255.224.0.0",
  48.             12 => "255.240.0.0",
  49.             13 => "255.248.0.0",
  50.             14 => "255.252.0.0",
  51.             15 => "255.254.0.0",
  52.             16 => "255.255.0.0",
  53.             17 => "255.255.128.0",
  54.             18 => "255.255.192.0",
  55.             19 => "255.255.224.0",
  56.             20 => "255.255.240.0",
  57.             21 => "255.255.248.0",
  58.             22 => "255.255.252.0",
  59.             23 => "255.255.254.0",
  60.             24 => "255.255.255.0",
  61.             25 => "255.255.255.128",
  62.             26 => "255.255.255.192",
  63.             27 => "255.255.255.224",
  64.             28 => "255.255.255.240",
  65.             29 => "255.255.255.248",
  66.             30 => "255.255.255.252",
  67.             31 => "255.255.255.254",
  68.             32 => "255.255.255.255"
  69.         );
  70. // }}}
  71. // {{{ Net_IPv4
  72.  
  73. /**
  74. * Class to provide IPv4 calculations
  75. *
  76. * Provides methods for validating IP addresses, calculating netmasks,
  77. * broadcast addresses, network addresses, conversion routines, etc.
  78. *
  79. * @category   Net
  80. * @package    Net_IPv4
  81. * @author     Eric Kilfoil <edk@ypass.net>
  82. * @author     Marco Kaiser <bate@php.net>
  83. * @author     Florian Anderiasch <fa@php.net>
  84. * @copyright  1997-2005 The PHP Group
  85. * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  86. * @version    CVS: 1.3.0
  87. * @link       http://pear.php.net/package/Net_IPv4
  88. * @access  public
  89. */
  90. class Net_IPv4
  91. {
  92.     // {{{ properties
  93.     var $ip = "";
  94.     var $bitmask = false;
  95.     var $netmask = "";
  96.     var $network = "";
  97.     var $broadcast = "";
  98.     var $long = 0;
  99.     
  100.     // }}}
  101.     // {{{ validateIP()
  102.  
  103.     /**
  104.      * Validate the syntax of the given IP adress
  105.      *
  106.      * Using the PHP long2ip() and ip2long() functions, convert the IP
  107.      * address from a string to a long and back.  If the original still
  108.      * matches the converted IP address, it's a valid address.  This
  109.      * function does not allow for IP addresses to be formatted as long
  110.      * integers.
  111.      *
  112.      * @param  string $ip IP address in the format x.x.x.x
  113.      * @return bool       true if syntax is valid, otherwise false
  114.      */
  115.     function validateIP($ip)
  116.     {
  117.         if ($ip == long2ip(ip2long($ip))) {
  118.             return true;
  119.         } else {
  120.             return false;
  121.         }
  122.     }
  123.     
  124.     // }}}
  125.     // {{{ check_ip()
  126.  
  127.     /**
  128.      * Validate the syntax of the given IP address (compatibility)
  129.      *
  130.      * This function is identical to Net_IPv4::validateIP().  It is included
  131.      * merely for compatibility reasons.
  132.      *
  133.      * @param  string $ip IP address
  134.      * @return bool       true if syntax is valid, otherwise false
  135.      */
  136.     function check_ip($ip)
  137.     {
  138.         return $this->validateIP($ip);
  139.     }
  140.  
  141.     // }}}
  142.     // {{{ validateNetmask()
  143.     
  144.     /**
  145.      * Validate the syntax of a four octet netmask
  146.      *
  147.      * There are 33 valid netmask values.  This function will compare the
  148.      * string passed as $netmask to the predefined 33 values and return
  149.      * true or false.  This is most likely much faster than performing the
  150.      * calculation to determine the validity of the netmask.
  151.      *
  152.      * @param  string $netmask Netmask
  153.      * @return bool       true if syntax is valid, otherwise false
  154.      */
  155.     function validateNetmask($netmask)
  156.     {
  157.         if (! in_array($netmask, $GLOBALS['Net_IPv4_Netmask_Map'])) {
  158.             return false;
  159.         }
  160.         return true;
  161.     }
  162.  
  163.     // }}}
  164.     // {{{ parseAddress()
  165.     
  166.     /**
  167.      * Parse a formatted IP address
  168.      *
  169.      * Given a network qualified IP address, attempt to parse out the parts
  170.      * and calculate qualities of the address.
  171.      *
  172.      * The following formats are possible:
  173.      *
  174.      * [dot quad ip]/[ bitmask ]
  175.      * [dot quad ip]/[ dot quad netmask ]
  176.      * [dot quad ip]/[ hex string netmask ]
  177.      *
  178.      * The first would be [IP Address]/[BitMask]:
  179.      * 192.168.0.0/16
  180.      *
  181.      * The second would be [IP Address] [Subnet Mask in dot quad notation]:
  182.      * 192.168.0.0/255.255.0.0
  183.      *
  184.      * The third would be [IP Address] [Subnet Mask as Hex string]
  185.      * 192.168.0.0/ffff0000
  186.      *
  187.      * Usage:
  188.      *
  189.      * $cidr = '192.168.0.50/16';
  190.      * $net = Net_IPv4::parseAddress($cidr);
  191.      * echo $net->network; // 192.168.0.0
  192.      * echo $net->ip; // 192.168.0.50
  193.      * echo $net->broadcast; // 192.168.255.255
  194.      * echo $net->bitmask; // 16
  195.      * echo $net->long; // 3232235520 (long/double version of 192.168.0.50)
  196.      * echo $net->netmask; // 255.255.0.0
  197.      *
  198.      * @param  string $ip IP address netmask combination
  199.      * @return object     true if syntax is valid, otherwise false
  200.      */
  201.     function parseAddress($address)
  202.     {
  203.         $myself = new Net_IPv4;
  204.         if (strchr($address, "/")) {
  205.             $parts = explode("/", $address);
  206.             if (! $myself->validateIP($parts[0])) {
  207.                 return PEAR::raiseError("invalid IP address");
  208.             }
  209.             $myself->ip = $parts[0];
  210.  
  211.             // Check the style of netmask that was entered 
  212.             /*
  213.              *  a hexadecimal string was entered
  214.              */
  215.             if (eregi("^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$", $parts[1], $regs)) {
  216.                 // hexadecimal string
  217.                 $myself->netmask = hexdec($regs[1]) . "." .  hexdec($regs[2]) . "." .
  218.                     hexdec($regs[3]) . "." .  hexdec($regs[4]);
  219.  
  220.             /*
  221.              *  a standard dot quad netmask was entered.
  222.              */
  223.             } else if (strchr($parts[1], ".")) {
  224.                 if (! $myself->validateNetmask($parts[1])) {
  225.                     return PEAR::raiseError("invalid netmask value");
  226.                 }
  227.                 $myself->netmask = $parts[1];
  228.  
  229.             /*
  230.              *  a CIDR bitmask type was entered
  231.              */
  232.             } else if ($parts[1] >= 0 && $parts[1] <= 32) {
  233.                 // bitmask was entered
  234.                 $myself->bitmask = $parts[1];
  235.  
  236.             /*
  237.              *  Some unknown format of netmask was entered
  238.              */
  239.             } else {
  240.                 return PEAR::raiseError("invalid netmask value");
  241.             }
  242.             $myself->calculate();
  243.             return $myself;
  244.         } else if ($myself->validateIP($address)) {
  245.             $myself->ip = $address;
  246.             return $myself;
  247.         } else {
  248.             return PEAR::raiseError("invalid IP address");
  249.         }
  250.     }
  251.     
  252.     // }}}
  253.     // {{{ calculate()
  254.     
  255.     /**
  256.      * Calculates network information based on an IP address and netmask.
  257.      *
  258.      * Fully populates the object properties based on the IP address and
  259.      * netmask/bitmask properties.  Once these two fields are populated,
  260.      * calculate() will perform calculations to determine the network and
  261.      * broadcast address of the network.
  262.      *
  263.      * @return mixed     true if no errors occured, otherwise PEAR_Error object
  264.      */
  265.     function calculate()
  266.     {
  267.         $validNM = $GLOBALS['Net_IPv4_Netmask_Map'];
  268.  
  269.         if (! is_a($this, "net_ipv4")) {
  270.             $myself = new Net_IPv4;
  271.             return PEAR::raiseError("cannot calculate on uninstantiated Net_IPv4 class");
  272.         }
  273.  
  274.         /* Find out if we were given an ip address in dot quad notation or
  275.          * a network long ip address.  Whichever was given, populate the
  276.          * other field
  277.          */
  278.         if (strlen($this->ip)) {
  279.             if (! $this->validateIP($this->ip)) {
  280.                 return PEAR::raiseError("invalid IP address");
  281.             }
  282.             $this->long = $this->ip2double($this->ip);
  283.         } else if (is_numeric($this->long)) {
  284.             $this->ip = long2ip($this->long);
  285.         } else {
  286.            return PEAR::raiseError("ip address not specified");
  287.         }
  288.  
  289.         /*
  290.          * Check to see if we were supplied with a bitmask or a netmask.
  291.          * Populate the other field as needed.
  292.          */
  293.         if (strlen($this->bitmask)) {
  294.             $this->netmask = $validNM[$this->bitmask];
  295.         } else if (strlen($this->netmask)) {
  296.             $validNM_rev = array_flip($validNM);
  297.             $this->bitmask = $validNM_rev[$this->netmask];
  298.         } else {
  299.             return PEAR::raiseError("netmask or bitmask are required for calculation");
  300.         }
  301.         $this->network = long2ip(ip2long($this->ip) & ip2long($this->netmask));
  302.         $this->broadcast = long2ip(ip2long($this->ip) |
  303.                 (ip2long($this->netmask) ^ ip2long("255.255.255.255")));
  304.         return true;
  305.     }
  306.  
  307.     // }}}
  308.     // {{{ getNetmask()
  309.     
  310.     function getNetmask($length)
  311.     {
  312.         if (! PEAR::isError($ipobj = Net_IPv4::parseAddress("0.0.0.0/" . $length))) {
  313.             $mask = $ipobj->netmask;
  314.             unset($ipobj);
  315.             return $mask;
  316.         }
  317.         return false;
  318.     }
  319.     
  320.     // }}}
  321.     // {{{ getNetLength()
  322.  
  323.     function getNetLength($netmask)
  324.     {
  325.         if (! PEAR::isError($ipobj = Net_IPv4::parseAddress("0.0.0.0/" . $netmask))) {
  326.             $bitmask = $ipobj->bitmask;
  327.             unset($ipobj);
  328.             return $bitmask;
  329.         }
  330.         return false;
  331.     }
  332.  
  333.     // }}}
  334.     // {{{ getSubnet()
  335.     
  336.     function getSubnet($ip, $netmask)
  337.     {
  338.         if (! PEAR::isError($ipobj = Net_IPv4::parseAddress($ip . "/" . $netmask))) {
  339.             $net = $ipobj->network;
  340.             unset($ipobj);
  341.             return $net;
  342.         }
  343.         return false;
  344.     }
  345.  
  346.     // }}}
  347.     // {{{ inSameSubnet()
  348.     
  349.     function inSameSubnet($ip1, $ip2)
  350.     {
  351.         if (! is_object($ip1) || strcasecmp(get_class($ip1), 'net_ipv4') <> 0) {
  352.             $ipobj1 = Net_IPv4::parseAddress($ip1);
  353.             if (PEAR::isError($ipobj)) {
  354.                 return PEAR::raiseError("IP addresses must be an understood format or a Net_IPv4 object");
  355.             }
  356.         }
  357.         if (! is_object($ip2) || strcasecmp(get_class($ip2), 'net_ipv4') <> 0) {
  358.             $ipobj2 = Net_IPv4::parseAddress($ip2);
  359.             if (PEAR::isError($ipobj)) {
  360.                 return PEAR::raiseError("IP addresses must be an understood format or a Net_IPv4 object");
  361.             }
  362.         }
  363.         if ($ipobj1->network == $ipobj2->network &&
  364.                 $ipobj1->bitmask == $ipobj2->bitmask) {
  365.                 return true;
  366.         }
  367.         return false;
  368.     }
  369.     
  370.     // }}}
  371.     // {{{ atoh()
  372.  
  373.     /**
  374.      * Converts a dot-quad formatted IP address into a hexadecimal string
  375.      * @param  string $addr IP-adress in dot-quad format
  376.      * @return mixed        false if invalid IP and hexadecimal representation as string if valid
  377.      */
  378.     function atoh($addr)
  379.     {
  380.         if (! Net_IPv4::validateIP($addr)) {
  381.             return false;
  382.         }
  383.         $ap = explode(".", $addr);
  384.         return sprintf("%02x%02x%02x%02x", $ap[0], $ap[1], $ap[2], $ap[3]);
  385.     }
  386.  
  387.     // }}}
  388.     // {{{ htoa()
  389.     
  390.     /**
  391.      * Converts a hexadecimal string into a dot-quad formatted IP address
  392.      * @param  string $addr IP-adress in hexadecimal format
  393.      * @return mixed        false if invalid IP and dot-quad formatted IP as string if valid
  394.      */
  395.     function htoa($addr)
  396.     {
  397.         if (eregi("^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$",
  398.                     $addr, $regs)) {
  399.             return hexdec($regs[1]) . "." .  hexdec($regs[2]) . "." .
  400.                    hexdec($regs[3]) . "." .  hexdec($regs[4]);
  401.         }
  402.         return false;
  403.     }
  404.     
  405.     // }}}
  406.     // {{{ ip2double()
  407.     
  408.     /**
  409.      * Converts an IP address to a PHP double.  Better than ip2long because
  410.      * a long in PHP is a signed integer.
  411.      * @param  string $ip  dot-quad formatted IP adress
  412.      * @return float       IP adress as double - positive value unlike ip2long
  413.      */
  414.     function ip2double($ip)
  415.     {
  416.         return (double)(sprintf("%u", ip2long($ip)));
  417.     }
  418.     
  419.     // }}}
  420.     // {{{ ipInNetwork()
  421.  
  422.     /**
  423.      * Determines whether or not the supplied IP is within the supplied network.
  424.      *
  425.      * This function determines whether an IP address is within a network.
  426.      * The IP address ($ip) must be supplied in dot-quad format, and the
  427.      * network ($network) may be either a string containing a CIDR
  428.      * formatted network definition, or a Net_IPv4 object.
  429.      *
  430.      * @param  string  $ip      A dot quad representation of an IP address 
  431.      * @param  string  $network A string representing the network in CIDR format or a Net_IPv4 object.
  432.      * @return bool             true if the IP address exists within the network
  433.      */
  434.     function ipInNetwork($ip, $network)
  435.     {
  436.         if (! is_object($network) || strcasecmp(get_class($network), 'net_ipv4') <> 0) {
  437.             $network = Net_IPv4::parseAddress($network);
  438.         }
  439.         
  440.         $net = Net_IPv4::ip2double($network->network);
  441.         $bcast = Net_IPv4::ip2double($network->broadcast);
  442.         $ip = Net_IPv4::ip2double($ip);
  443.         unset($network);
  444.         if ($ip >= $net && $ip <= $bcast) {
  445.             return true;
  446.         }
  447.         return false;
  448.     }
  449.     
  450.     // }}}
  451. }
  452.  
  453. // }}}
  454.  
  455. /*
  456.  * vim: sts=4 ts=4 sw=4 cindent fdm=marker
  457.  */
  458. ?>
  459.